#include "SynthObject.h"
#include "cinder/app/AppBasic.h"
#include "Global.h"
#include "cinder/gl/Texture.h"
#include "cinder/gl/TextureFont.h"
#include "cinder/ImageIo.h"

using namespace std;

using namespace cinder;

SynthObject::SynthObject( string synthName, float x, float y,float param1, float param2,int section, cinder::gl::TextureFontRef textureFont) :
    synthName(synthName),
    x(x),
    y(y),
    param1(param1),
    param2(param2),
    section(section),
    flicker(1),
    flickerCount(0),
    bufferSize(512),
    mTextureFont(textureFont),
    textCounter(0)
{
    cout << "SynthObject created: " << synthName <<  x << y << param1 << param2 << endl;
    count = param1 + 0.1;
    //qsrand((uint)time.msec()+param1-param2);

    rotateAmt =rand()%1;
    redDelta = rand()%1;
    blueDelta = rand()%1;
    greenDelta = rand()%1;
    for(int i=0;i<10;i++) {
        reds.push_back(rand()%1);
        greens.push_back(rand()%1);
        blues.push_back(rand()%1);
    }
    for(int i=0;i<bufferSize;i++) {
        this->buffer.push_back(0.0f);
    }
}

void SynthObject::draw() {
    count = count + (param2*0.025f);
    rotateAmt = rotateAmt+ (param1*0.01f);
    redDelta = redDelta + (param2*0.02f);
    blueDelta = blueDelta + (param1*0.05f);
    greenDelta = greenDelta + (param2*0.025f);
    flickerCount = flickerCount+1;
    /*
    for(int i=0;i<10;i++) {
        reds.replace(i,reds.at(i) + fmod(rand(),0.5));
        greens.replace(i,greens.at(i) + fmod(rand(),0.5));
        blues.replace(i,blues.at(i) + fmod(rand(),0.5));
    }
    */

    glLineWidth(2.0f);
    switch(section) {
        case 1:
            glLineWidth(1);
            //glColor4f(1,1,1,0.5);
            glColor4f(0,0,0,0.5);
            gl::drawStrokedCircle(Vec2f(x,y),40,40);
            glLineWidth(8);

            glBegin(GL_LINE_STRIP);
            for(int i=0;i<360;i+=1) {
                glColor4f(1,1,1,1.5);
                glVertex2f(x + (sin(i*(3.141592654/180)) * ((buffer.at(i*0.25)*60)+40)), y + (cos(i*(3.141592654/180)) * ((buffer.at(i*0.25)*60)+40)));
                //glColor4f(0,0,0,0.0);
                //gl::color(ColorA(0,0,0,1));
                //gl::drawSolidCircle(Vec2f(x + (sin(i) * 120 ),y + (cos(i) * 120 )),300*buffer.at(i),12);
            }
            glEnd();
            glLineWidth(4);
            glBegin(GL_LINE_STRIP);
            for(int i=0;i<360;i+=1) {
                glColor4f(0,0,0,0.5);
                glVertex2f(x + (sin(i) * (buffer.at(i)*90)), y + (cos(i) * (buffer.at(i)*90)));
                //glColor4f(0,0,0,0.0);
                //gl::color(ColorA(0,0,0,1));
                //gl::drawSolidCircle(Vec2f(x + (sin(i) * 120 ),y + (cos(i) * 120 )),300*buffer.at(i),12);
            }
            glEnd();

            glColor4f(0,0,0,0.5);
            //gl::drawSolidCircle(Vec2f(x,y),40*fabs(sin(redDelta*0.2)),30);
            break;
        case 2:

            glLineWidth(1.0);
            glColor4f(1,1,1,1.0);

            gl::pushMatrices();
            gl::translate(x,y,0);
            gl::rotate(180+(param2*360));
            gl::drawStrokedCircle(Vec2f(0,-20),40,40);
            gl::popMatrices();

            gl::pushMatrices();
            gl::translate(x,y,0);
            gl::rotate(180+(param1*360));
            //glColor4f((sin(redDelta)*0.25)+0.5*0.1*0.01,sin(greenDelta)*0.5+ 0.25,(sin(blueDelta)*0.75)+0.5,0.001);
            glColor4f((sin(redDelta)*0.25)*0.5,sin(greenDelta)*0.5,(sin(blueDelta)*0.75)+0.5,0.001);
            gl::drawSolidCircle(Vec2f(0,-13),25*fabs(sin(redDelta*0.4))*(this->buffer.at(0)*1.75+1.25),30);
            gl::popMatrices();

            break;
        case 3:
            if(flickerCount !=5) {
                gl::enableAdditiveBlending();
            }
            if(flickerCount == 5) {
                flicker = 0;
                glColor4f(0,0,0,1);
                gl::drawSolidCircle(Vec2f(x,y),40,40);
            } else if (flickerCount ==10) {

                flicker = 1;
                flickerCount=0;
            }
            gl::enableAdditiveBlending();
            //if(flickerCount > 5) {

            //}
            glLineWidth(1.0);

            glLineWidth(0.1);
            glColor4f(1,1,1,1*flicker*fabs(sin(redDelta*4.2)));
            gl::drawSolidCircle(Vec2f(x,y),((buffer.at(0)*180)+20)*0.125,10);
            /*
            glBegin(GL_LINE_STRIP);
            for(int i=0;i<360;i+=1) {
                //glColor4f(1,1,1,1.5);
                glVertex2f(x + (sin(i) * ((buffer.at(i)*60)+40))*0.125, y + (cos(i) * ((buffer.at(i)*60)+40))*0.125);
                //glColor4f(0,0,0,0.0);
                //gl::color(ColorA(0,0,0,1));
                //gl::drawSolidCircle(Vec2f(x + (sin(i) * 120 ),y + (cos(i) * 120 )),300*buffer.at(i),12);
            }

            glEnd();
            */

            //gl::drawStrokedCircle(Vec2f(x,y),40,40);
            //glLineWidth(6.0);
            float red = fmod( ((sin(redDelta*0.25)*0.25))*0.5,0.25);
            float green = fmod(sin(greenDelta*0.5)*0.1,0.125);
            float blue = fmod(sin(blueDelta*0.5)*0.25,0.5);
            float alpha = 0.25 * (flicker)*fabs(sin(redDelta*4.2));
            glColor4f(red,green,blue,alpha);
            //glColor4f(sin(greenDelta)*0.25 +0.25,sin(greenDelta)*0.25 +0.25,sin(greenDelta)*0.25 +0.25,0.75);
            //gl::drawSolidCircle(Vec2f(x,y),40,40);
            //glVertex2f(x, y);
            glLineWidth(1.0);
            glBegin(GL_LINE_STRIP);
            for(int i=0;i<360;i+=1) {
                //glColor4f(1,1,1,1.5);
                glVertex2f(x + (sin(i) * ((buffer.at(0)*140)+10)), y + (cos(i) * ((buffer.at(0)*140)+10)));
                //glColor4f(0,0,0,0.0);
                //gl::color(ColorA(0,0,0,1));
                //gl::drawSolidCircle(Vec2f(x + (sin(i) * 120 ),y + (cos(i) * 120 )),300*buffer.at(i),12);
            }
            glEnd();


            //try multi-color circles some HWO? differnet color for each vertex
            //glCircle3i(x,y,40);
            //glBegin(GL_QUADS);
            //glVertex2f()

            //glEnd();

            /*
            glBegin(GL_TRIANGLE_FAN);
            glVertex2f(x, y);
            for(int angle=0;angle<360;angle+=60) {
                glColor4f((sin(reds.at(fmod(angle,10)))+0.25)*0.25,(sin(greens.at(fmod(angle,10)))+0.25)*0.25,(sin(blues.at(fmod(angle,10)))+0.5)*0.5,0.5);
                glVertex3f(x + sin(angle) * 40, y + cos(angle) * 40,-100);
            }
            glEnd();
            */
        break;
    }

    //if(Curse::SECTION ==1) {

        //cout <<4;
    //}


    //Draw Objects

    //glColor4f(1,1,1,0.6);
    //gl::drawStrokedCircle(Vec2f(x,y),40,40);
    //gl::drawStrokedCircle(Vec2f(x,y),40*fabs(sin(count*4.2)),40);
    //glColor4f((sin(redDelta)*0.25)+0.5*0.1*0.01,sin(greenDelta)*0.5+ 0.25,(sin(blueDelta)*0.75)+0.5,0.025);


    //glColor4f((sin(redDelta)*0.25)+0.5*0.1*0.00,sin(greenDelta)*0.5,(sin(blueDelta)*0.75)+0.25,0.4);
    //glColor4f(0,0,0,0.5);
    //gl::drawSolidCircle(Vec2f(x,y),40*fabs(sin(redDelta*4.2)),30);
    glColor4f(1,1,1,0.25);
    //glColor4d((sin(redDelta)*0.25)+0.5*0.1,sin(greenDelta)*0.5+ 0.25,(sin(blueDelta)*0.75)+0.5,0.025);
    //gl::drawStrokedCircle(Vec2f(x,y),70,40);
}

void SynthObject::drawMetaSynth()
{
    switch(section) {
        case 1:
            break;
        case 2:
            glLineWidth(2.0f);
            glColor4f(1,1.0,1.0,1);
            //gl::drawStrokedCircle(Vec2f(x,y),20+ (buffer.at(0)*10),20);
            break;
        case 3:
            glLineWidth(2.0f);
            glColor4f(1,1.0,1.0,1);
            //gl::drawStrokedCircle(Vec2f(x,y),20+ (buffer.at(0)*10),20);
            break;
    }
    textCounter++;
    if(textCounter < 150) {
        gl::color( ColorA( 1,1,1,1.0 ) );
        mTextureFont->drawString(synthName,Rectf(x,y+50,x+200,y+900));
    }
    gl::pushMatrices();
    gl::translate(x,y,0);
    gl::rotate(180+(param1*360));
    gl::drawStrokedCircle(Vec2f(0,-15),30,60);
    //gl::drawLine(Vec2f(0,0),Vec2f(0,-30));
    gl::popMatrices();

    gl::pushMatrices();
    gl::translate(x,y,0);
    gl::rotate(180+(param2*360));
    gl::drawStrokedCircle(Vec2f(0,-15),30,60);
    //gl::drawLine(Vec2f(0,0),Vec2f(0,-30));
    gl::popMatrices();
}

void SynthObject::glCircle3i(int x, int y, int radius)
{
    /*
    glPushMatrix();
    glLoadIdentity();
    //glColor4ub(r, g, b, a);
    glColor4f(1,1,1,1);
    //glDisable(GL_TEXTURE_2D);
    glLineWidth(1.0f);
    glBegin(GL_POLYGON);
    glVertex2i(x+radius, y); //freebies
    glVertex2i(x-radius, y);
    glVertex2i(x, y+radius);
    glVertex2i(x, y-radius);
    float xmod, ymod, step = 3.141592654 / (4*radius); //don't compute much more than is necessary for a solid circle
    for(float theta = 0; theta <= 3.141592654/2; theta += step)
    {

        xmod = (cos(theta) * radius);
        ymod = (sin(theta) * radius);
        //glColor4f(1,1,1,0.5);
        glVertex2f(x + xmod, y + ymod); //create solids by vertices
        //glColor4f(reds.at(fmod(theta,40)),greens.at(fmod(theta,40)),blues.at(fmod(theta,40)),0.5);
        glVertex2f(x + xmod, y - ymod); //and using glpolygon for filling
        //glColor4f(reds.at(fmod(theta,40)),greens.at(fmod(theta,40)),blues.at(fmod(theta,40)),0.5);
        glVertex2f(x - xmod, y + ymod);
        //glColor4f(reds.at(fmod(theta,40)),greens.at(fmod(theta,40)),blues.at(fmod(theta,40)),0.5);
        glVertex2f(x - xmod, y - ymod);
    }
    glEnd();
    //glEnable(GL_TEXTURE_2D);
    glPopMatrix();
    */

    glBegin(GL_TRIANGLE_FAN);
    glVertex2f(x, y);
    //for angle# = 0 to 360 step 5
    for(int angle;angle<360;angle+=5) {
        glVertex2f(x + sin(angle) * radius, y + cos(angle) * radius);
    }
    //next
    glEnd();
}


void SynthObject::setSynthName(string synthName) {
    this->synthName = synthName;
}

void SynthObject::setX(float x) {
    this->x = x;
}

void SynthObject::setY(float y) {
   this->y = y;
}

void SynthObject::setParam1(float param1) {
    this->param1 = param1;
}

void SynthObject::setParam2(float param2) {
    this->param2 = param2;
}

void SynthObject::setSynthSelection(string synthSelection) {
    this->synthSelection = synthSelection;
}

void SynthObject::setSection(int section)
{
    this->section = section;
}

void SynthObject::setAudioBuffer(vector<float> buffer)
{
    this->buffer = buffer;
}

float SynthObject::getX()
{
    return x;
}

float SynthObject::getY()
{
    return y;
}
